#ifndef __UDSF_MEMORY_ACCESS_C_
#define __UDSF_MEMORY_ACCESS_C_

#include "sdk_ifs_udk_cfg.h"
#include "../udsf/udsf_spiflash.c"
#include "../udsf/udsf_crc.c"
#include "../udsf/udsf_uart.c"
#include "../udsf/udsf_cstdlike.c"

/*
*   notice:
*   UDSF 同UDF编程：不可调用cstd-lib,只可调用"sdk_ifs_udk_cfg.h"、"sys_api.h"中列出的API函数。
*   UDSF文件内函数均需使用static修饰符，且UDF中以#include "UDSF.c"形式引用
*/

static void udsf_memory_load2sram( uint32_t addr,uint8_t is_xip,uint8_t udt_src,uint8_t*buff,uint32_t len) __attribute__((unused));
static void udsf_memory_program( uint32_t addr,uint8_t is_xip,uint8_t udt_src,uint8_t* buff,uint32_t len) __attribute__((unused));

static void udsf_memory_load2sram( uint32_t addr,uint8_t is_xip,uint8_t udt_src,uint8_t*buff,uint32_t len){

	// rom / xip48k内 统一 定义为内部。rom启动flash/xip大于48K定义为 外部。
	if( !is_xip && (udt_src == UDT_SRC_OUTER) ){ // rom 启动，外部flash内udt->spiflash访问

		//udsf_uart_send_u32_base16(1,&addr,1,"[USRBOOT]:ADDR:","\n");
		
		udsf_spiflash_read_data(buff,addr,len);
	}else{
		if( is_xip && (udt_src == UDT_SRC_OUTER) ){ // xip 启动 48K外flash增加偏移
			addr += SYSBIN_SIZE_MAX;
		}

		//udsf_uart_send_u32_base16(1,&addr,1,"[USRBOOT]:ADDR:","\n");

		udsf_memcpy((uint8_t*)addr,buff,len);
	}
	
}

static void udsf_memory_program( uint32_t addr,uint8_t is_xip,uint8_t udt_src,uint8_t* buff,uint32_t len){
	
	if( is_xip && (udt_src == UDT_SRC_OUTER ) ){
		addr += SYSBIN_SIZE_MAX;
	}
	
	len = SYS_ALIGN(len,FLASH_SECTOR_SIZE);
	
	if( is_xip ){
		// isr disable
		NVIC->ICER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
		// xip disable
		QSPI->CTRL = (QSPI_CTRL_IE_Msk                                       |\
		QSPI_CTRL_MSB_SEL_Msk                                  |\
		(QSPI_STANDARD << QSPI_CTRL_FRAME_MODE_Pos)            |\
		(QSPI_CLOCK_DIV << QSPI_CTRL_CLK_DIV_Pos)              |\
		(QSPI_DUMMY_DATA_LEN_QUAD << QSPI_CTRL_DUMMY_LEN_Pos)  |\
		(QSPI_READ_CMD_QUAD << QSPI_CTRL_READ_COMMAND_Pos));
	}
	
	for( int i=0;i<len/FLASH_SECTOR_SIZE;i++ ){
		udsf_spiflash_erase_sector(addr+i*FLASH_SECTOR_SIZE);
		for( int j=0;j<FLASH_PAGE_PER_SECTOR;j++ ){
			udsf_spiflash_write_data(buff+i*FLASH_SECTOR_SIZE+j*FLASH_PAGE_SIZE,addr+i*FLASH_SECTOR_SIZE+j*FLASH_PAGE_SIZE,FLASH_PAGE_SIZE);
		}
	}
	
	if( is_xip ){
		// xip enable
		QSPI->CTRL = (QSPI_CTRL_BOOT_SEL_Msk                                |\
						 QSPI_CTRL_MSB_SEL_Msk                                 |\
						(QSPI_QUAD_INPUT << QSPI_CTRL_FRAME_MODE_Pos)          |\
						(QSPI_CLOCK_DIV << QSPI_CTRL_CLK_DIV_Pos)              |\
						(QSPI_DUMMY_DATA_LEN_QUAD << QSPI_CTRL_DUMMY_LEN_Pos)  |\
						(QSPI_READ_CMD_QUAD << QSPI_CTRL_READ_COMMAND_Pos));   
		QSPI->CS = 0x0000;
		QSPI->CS |= (QSPI_CS_XIP_ON_Msk | QSPI_CS_CS_HIGH);
		// isr enable
		NVIC->ISER[0] = (1 << ((uint32_t)(USCI1_IRQn) & 0x1F));
	}
}

#endif
